package com.seagox.chat.chat.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.seagox.chat.chat.entity.ChatContact;
import com.seagox.chat.chat.entity.ChatMessage;
import com.seagox.chat.chat.entity.ChatRoom;
import com.seagox.chat.chat.entity.BaseUser;
import com.seagox.chat.chat.mapper.ChatContactMapper;
import com.seagox.chat.chat.mapper.ChatMessageMapper;
import com.seagox.chat.chat.mapper.ChatRoomMapper;
import com.seagox.chat.chat.mapper.UserMapper;
import com.seagox.chat.chat.service.IChatRoomService;
import com.seagox.chat.common.ResultData;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ChatRoomService implements IChatRoomService {
    
    @Autowired
    private ChatRoomMapper chatRoomMapper;
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
    
    @Autowired
    private ChatContactMapper chatContactMapper;
    
    @Autowired
    private ChatMessageMapper chatMessageMapper;

	@Override
	public ResultData queryById(String id) {
		ChatRoom chatRoom = chatRoomMapper.selectById(id);
		List<String> userList = new ArrayList<>(Arrays.asList(chatRoom.getMembers().split(",")));
		userList.remove(chatRoom.getOwner());
		LambdaQueryWrapper<BaseUser> qw = new LambdaQueryWrapper<>();
		qw.in(BaseUser::getId, userList);
		List<BaseUser> memberList = userMapper.selectList(qw);
		BaseUser user = userMapper.selectById(chatRoom.getOwner());
		memberList.add(0, user);
		chatRoom.setMemberList(memberList);
		return ResultData.success(chatRoom);
	}
	
	@Transactional
	@Override
	public ResultData addMember(String userId, String sessionId, String data) {
		ChatRoom chatRoom = chatRoomMapper.selectById(sessionId);
		List<String> memberList = new ArrayList<>(Arrays.asList(chatRoom.getMembers().split(",")));
		JSONArray userData = JSONArray.parseArray(data);
		for (int i = 0; i < userData.size(); i++) {
			JSONObject user = userData.getJSONObject(i);
			memberList.add(user.getString("id"));
			LambdaQueryWrapper<ChatContact> qw = new LambdaQueryWrapper<>();
			qw.eq(ChatContact::getSessionId, sessionId).eq(ChatContact::getSource, user.getString("id"));
			ChatContact chatContact = chatContactMapper.selectOne(qw);
			if(chatContact != null) {
				chatContact.setFlag(1);
				chatContactMapper.update(chatContact, qw);
			} else {
				chatContact = new ChatContact();
				chatContact.setClassify(2);
				chatContact.setTarget(userId);
				chatContact.setContent("");
				chatContact.setFlag(1);
				chatContact.setName(chatRoom.getName());
				chatContact.setType(1);
				chatContact.setUnread(0);
				chatContact.setSource(user.getString("id"));
				chatContact.setSessionId(chatRoom.getId());
				chatContact.setMsgid(String.valueOf(System.currentTimeMillis()));
				chatContactMapper.insert(chatContact);
			}
		}
		chatRoom.setMembers(String.join(",", memberList));
		chatRoomMapper.updateById(chatRoom);
		JSONObject message = new JSONObject();
		message.put("type", "add");
		message.put("sessionId", sessionId);
		message.put("target", memberList);
		redisTemplate.convertAndSend("room", message.toJSONString());
		return ResultData.success(null);
	}
	
	@Transactional
	@Override
	public ResultData removeMember(String userId, String sessionId, String data) {
		ChatRoom chatRoom = chatRoomMapper.selectById(sessionId);
		List<String> targetList = Arrays.asList(chatRoom.getMembers().split(","));
		List<String> memberList = new ArrayList<>(Arrays.asList(chatRoom.getMembers().split(",")));
		List<String> removeList = new ArrayList<String>();
		JSONArray userData = JSONArray.parseArray(data);
		for (int i = 0; i < userData.size(); i++) {
			JSONObject user = userData.getJSONObject(i);
			memberList.remove(user.getString("id"));
			removeList.add(user.getString("id"));
			LambdaQueryWrapper<ChatContact> qw = new LambdaQueryWrapper<>();
			qw.eq(ChatContact::getSessionId, sessionId).eq(ChatContact::getSource, user.getString("id"));
			ChatContact chatContact = chatContactMapper.selectOne(qw);
			if(chatContact != null) {
				chatContact.setType(1);
				chatContact.setContent("");
				chatContact.setUnread(0);
				chatContact.setFlag(0);
				chatContactMapper.update(chatContact, qw);
			}
			LambdaQueryWrapper<ChatMessage> dw = new LambdaQueryWrapper<>();
			dw.eq(ChatMessage::getSessionId, sessionId).eq(ChatMessage::getTarget, user.getString("id"));
			chatMessageMapper.delete(dw);
		}
		chatRoom.setMembers(String.join(",", memberList));
		chatRoomMapper.updateById(chatRoom);
		JSONObject message = new JSONObject();
		message.put("type", "remove");
		message.put("sessionId", sessionId);
		message.put("source", removeList);
		message.put("target", targetList);
		redisTemplate.convertAndSend("room", message.toJSONString());
		return ResultData.success(null);
	}

	@Transactional
	@Override
	public ResultData modifyName(String userId, String sessionId, String name) {
		ChatRoom chatRoom = chatRoomMapper.selectById(sessionId);
		chatRoom.setName(name);
		chatRoomMapper.updateById(chatRoom);
		LambdaQueryWrapper<ChatContact> uw = new LambdaQueryWrapper<>();
		uw.eq(ChatContact::getSessionId, sessionId).eq(ChatContact::getClassify, 2);
		ChatContact chatContact = new ChatContact();
		chatContact.setName(name);
		chatContactMapper.update(chatContact, uw);
		JSONObject message = new JSONObject();
		message.put("type", "modify");
		message.put("sessionId", sessionId);
		message.put("name", name);
		List<String> memberList = new ArrayList<>(Arrays.asList(chatRoom.getMembers().split(",")));
		message.put("target", memberList);
		redisTemplate.convertAndSend("room", message.toJSONString());
		return ResultData.success(null);
	}
	
	@Transactional
	@Override
	public ResultData quit(String userId, String sessionId) {
		ChatRoom chatRoom = chatRoomMapper.selectById(sessionId);
		List<String> target = Arrays.asList(chatRoom.getMembers().split(","));
		List<String> memberList = new ArrayList<>(Arrays.asList(chatRoom.getMembers().split(",")));
		memberList.remove(userId);
		if(userId.equals(chatRoom.getOwner())) {
			chatRoom.setOwner(memberList.get(0));
		}
		chatRoom.setMembers(String.join(",", memberList));
		chatRoomMapper.updateById(chatRoom);
		LambdaQueryWrapper<ChatContact> qw = new LambdaQueryWrapper<>();
		qw.eq(ChatContact::getSessionId, sessionId).eq(ChatContact::getSource, userId);
		ChatContact chatContact = chatContactMapper.selectOne(qw);
		if(chatContact != null) {
			chatContact.setType(1);
			chatContact.setContent("");
			chatContact.setFlag(0);
			chatContactMapper.update(chatContact, qw);
		}
		JSONObject message = new JSONObject();
		message.put("type", "quit");
		message.put("sessionId", sessionId);
		message.put("source", userId);
		message.put("target", target);
		redisTemplate.convertAndSend("room", message.toJSONString());
		return ResultData.success(null);
	}
	
}
